package com.example.javascaffold.utils;

import com.example.javascaffold.constant.Constant;
import com.example.javascaffold.exception.BaseException;
import com.example.javascaffold.exception.ParamException;

import java.util.Calendar;
import java.util.Date;


/**
 * <p><strong>时间工具类</strong></p>
 * <p>
 *     获取时间: 昨天, 今天, 明天。<br>
 * </p>
 * <li>
 * <p>
 *     <strong>示例1: 根据出生日期获取年龄 </strong> <br>
 *     DateUtils.getAge(出生日期); <br>
 *     返回结果: 24 <br>
 * </p>
 * </li>
 * <li>
 * <p>
 *     <strong>示例2: 当前日期前后的日期 num大于0则日期往后 小于0则日期往前</strong> <br>
 *     DateUtils.getDay(num); <br>
 *     返回结果: 2021-8-11 16:06:31 <br>
 * </p>
 * </li>
 * <li>
 * <p>
 *     <strong>示例3: 指定日期前后的日期 num大于0则日期往后 小于0则日期往前</strong> <br>
 *     DateUtils.getDay(date, num);<br>
 *     返回结果: 2021-8-11 16:06:31 <br>
 * </p>
 * </li>
 * <li>
 * <p>
 *     <strong>示例4: 指定日期前后的日期</strong> <br>
 *     DateUtils.getDay(day, minutes);<br>
 *     返回结果: 2021-8-11 16:06:31 <br>
 * </p>
 * </li>
 * <li>
 * <p>
 *     <strong>示例5: 指定日期前后的日期</strong> <br>
 *     DateUtils.getDay(date, day, minutes);<br>
 *     返回结果: 2021-8-11 16:06:31 <br>
 * </p>
 * </li>
 * <li>
 * <p>
 *     <strong>示例6: 计算两个时间间隔月数</strong> <br>
 *     DateUtils.getMonths(startTime, endTime);<br>
 *     返回结果: 24 <br>
 * </p>
 * </li>
 * @author song
 * @see Calendar
 * @see Date
 * @since 16:44 2021/8/6
 **/
public class DateUtils {

    private DateUtils() {}

    /**
     * <p>
     *     <strong>示例1: 计算年龄</strong> <br>
     *     DateUtils.getAge(出生日期); <br>
     *     返回结果: 24 <br>
     * </p>
     * @param birthDay 日期
     * @return int 年龄
     * @author song
     * @since 16:44 2021/8/6
     **/
    public static  int getAge(Date birthDay) throws BaseException {
        if (CheckParamUtils.isNullOrEmpty(birthDay)) {
            return 0;
        }
        Calendar cal = Calendar.getInstance();
        if (cal.before(birthDay)) {
            // 出生日期晚于当前时间，无法计算
            throw new ParamException("日期不可用");
        }
        // 当前年份
        int yearNow = cal.get(Calendar.YEAR);
        // 当前月份
        int monthNow = cal.get(Calendar.MONTH);
        // 当前日期
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birthDay);
        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
        // 计算整岁数
        int age = yearNow - yearBirth;
        if (monthNow <= monthBirth) {
            if (monthNow == monthBirth) {
                if (dayOfMonthNow < dayOfMonthBirth) {
                    // 当前日期在生日之前，年龄减一
                    age--;
                }
            }else{
                // 当前月份在生日之前，年龄减一
                age--;
            }
        }
        return age;
    }

    /**
     * <p>
     *     <strong>示例2: 当前日期前后的日期</strong> <br>
     *     DateUtils.getDay(day); <br>
     *     返回结果: 2021-8-11 16:06:31 <br>
     * </p>
     * @param day 大于0则日期往后 小于0则日期往前
     * @return date
     * @author song
     * @since 15:11 2021/9/17
     **/
    public static Date getDay(int day) {
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // num 负数 日期往前、 num 正数 日期往后
        calendar.add(Calendar.DAY_OF_MONTH, day);
        return calendar.getTime();
    }

    /**
     * @author : song
     * @date    : 2021/10/15 13:13
     * @description 获取某天的凌晨时刻
     */
    public static Date getDayBreak(int day) {
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        // num 负数 日期往前、 num 正数 日期往后
        calendar.add(Calendar.DAY_OF_MONTH, day);
        return calendar.getTime();
    }


    /**
     * <p>
     *     <strong>示例3: 指定日期前后的日期</strong> <br>
     *     DateUtils.getDay(date, day);<br>
     *     返回结果: 2021-8-11 16:06:31 <br>
     * </p>
     * @param day 大于0则日期往后 小于0则日期往前
     * @return date
     * @author song
     * @since 15:13 2021/9/17
     **/
    public static Date getDay(Date date, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // num 负数 日期往前、 num 正数 日期往后
        calendar.add(Calendar.DAY_OF_MONTH, day);
        return calendar.getTime();
    }

    /**
     * <p>
     *     <strong>示例4: 指定日期前后的日期</strong> <br>
     *     DateUtils.getDay(day, minutes);<br>
     *     返回结果: 2021-8-11 16:06:31 <br>
     * </p>
     * @param day 大于0则日期往后 小于0则日期往前
     * @param minutes 大于0则日期往后 小于0则日期往前
     * @return date
     * @author song
     * @since 15:18 2021/9/17
     **/
    public static Date getDay(int day, int minutes) {
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // num 负数 日期往前、 num 正数 日期往后
        calendar.add(Calendar.DAY_OF_MONTH, day);
        calendar.add(Calendar.MINUTE, minutes);
        return calendar.getTime();
    }

    /**
     * <p>
     *     <strong>示例5: 指定日期前后的日期</strong> <br>
     *     DateUtils.getDay(date, day, minutes);<br>
     *     返回结果: 2021-8-11 16:06:31 <br>
     * </p>
     * @param day 大于0则日期往后 小于0则日期往前
     * @param minutes 大于0则日期往后 小于0则日期往前
     * @return date
     * @author song
     * @since 15:18 2021/9/17
     **/
    public static Date getDay(Date date, int day, int minutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // num 负数 日期往前、 num 正数 日期往后
        calendar.add(Calendar.DAY_OF_MONTH, day);
        calendar.add(Calendar.MINUTE, minutes);
        return calendar.getTime();
    }

    /**
     * <p>
     *     <strong>示例6: 计算两个时间间隔月数</strong> <br>
     *     DateUtils.getMonths(startTime, endTime);<br>
     *     返回结果: 24 <br>
     * </p>
     * @author song
     * @date 15:29 2021/10/9
     * @param startTime 起始时间
     * @param endTime 截至时间
     * @return
     * @other
    **/
    public static int getComputeMonths(Date startTime, Date endTime) throws BaseException {
        // 判空
        if (CheckParamUtils.isNullOrEmpty(startTime) || CheckParamUtils.isNullOrEmpty(endTime)) {
            throw new ParamException("请确认startTime和endTime参数不为空!");
        }
        // 判断起始时间与截至时间大小
        if (endTime.compareTo(startTime) < 0) {
            return 0;
        }
        // 并为操作日历字段提供了一些方法
        Calendar cal = Calendar.getInstance();
        cal.setTime(startTime);
        // 起始时间年份
        int startTimeYear = cal.get(Calendar.YEAR);
        // 起始时间月份
        int startTimeMonth = cal.get(Calendar.MONTH);
        cal.setTime(endTime);
        // 截至时间年份
        int endTimeYear = cal.get(Calendar.YEAR);
        // 截至时间月份
        int endTimeMonth = cal.get(Calendar.MONTH);
        return (endTimeYear - startTimeYear) * Constant.ONE_YEAR_MONTHS - (startTimeMonth - endTimeMonth);
    }

}

